import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5 import uic

from collections import deque
import time
import threading
import  os
import pyttsx3
import pygame


class TimerWindowShow(QWidget):
    showSignal = pyqtSignal(QWidget)
    subsubsub_window_signal = pyqtSignal()  # 定义一个信号
    def __init__(self,total_seconds=None,ShowData=None,mode=None,event_listener=None,getdatalists=None,TheTimerId='NULL',lcdsetStyleSheet=None):
        super().__init__()
        # loader = uic.loadUi
        print('get:',getdatalists)
        self.getdatalists = getdatalists
        self.TheTimerId=TheTimerId

        self.event_listener = event_listener

        self.total_seconds = total_seconds
        self.currentSeconds=self.total_seconds


        self.mode=mode
        self.ShowData = ShowData
        self.lcdsetStyleSheet=lcdsetStyleSheet

        self.ui = uic.loadUi(r'..\ui\\TimerWindowsShow.ui')
        self.ui._startPos = None
        self.ui._endPos = None
        self.ui._tracking = False

        self.hidden=False
        self.screen_width = QDesktopWidget().screenGeometry().width()
        print('screen_width:',self.screen_width)

        self.originWindowWidth=self.ui.width()
        self.originWindowHeight=self.ui.height()

        # 在 self.ui 上添加右键菜单
        self.ui.setContextMenuPolicy(3)  # 设置右键菜单策略为 CustomContextMenu
        self.ui.customContextMenuRequested.connect(self.showContextMenu)

        # self.ui.resize(240, 100)

        # # 窗体置顶(窗体置顶，仅仅为了方便测试)，去边框
        # self.ui.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)

        # 设置窗口可缩放
        self.ui.setWindowFlags(Qt.WindowStaysOnTopHint)
        self.ui.setWindowFlag(Qt.FramelessWindowHint, True)  # 移除无边框窗口标志
        # self.ui.setWindowFlag(Qt.WindowMinMaxButtonsHint, True)  # 显示最小化和最大化按钮
        #窗体透明，控件不透明
        self.setAttribute(Qt.WA_TranslucentBackground)

        self.lcdNumber = self.ui.findChild(QLCDNumber)
        self.lcdNumber.setStyleSheet(self.lcdsetStyleSheet)
        # print(self.lcdNumber)
        self.ShowImfornation = self.ui.findChild(QTextEdit, 'ShowData')
        self.ShowImfornation.setCursorWidth(0)  # 隐藏光标

        self.updateDisplay()
        self.UpdataShowData()
        self.InitPushButton()
        if self.getdatalists is not None:
            self.dataNoneFlag=True
            self.getdatalistsHand(self.getdatalists)
        else:
            self.dataNoneFlag=False

        if mode == 'OtherMode':
            self.OtherMode_Changeui()

        self.ui.show()
        # 安装事件过滤器
        self.ui.installEventFilter(self)

    def on_event_TimerWork(self):
        self.TimerWork_ready()
        print("TimerWork Runing")

    def on_event_TimerStop(self):
        self.TimerStop()
        print("TimerStopped")

    def on_event_CloseUi(self):
        # print("隐藏TimerShow")
        # self.ui.hide()
        self.ui.resize(self.originWindowWidth, self.originWindowHeight)
        x=QApplication.desktop().screenGeometry().width()//2-self.originWindowWidth//2
        y=QApplication.desktop().screenGeometry().height()//2-self.originWindowHeight//2
        self.ui.move(x,y)

        self.subsubsub_window_signal.emit()  # 触发信号

        # self.close()

    def register_for_event(self):
        self.event_listener.register_callback1(self.on_event_TimerWork)
        self.event_listener.register_callback2(self.on_event_TimerStop)
        self.event_listener.register_callback3(self.on_event_CloseUi)


    def OtherMode_Changeui(self):
        self.ShowImfornation.hide()
        self.AddTimes.hide()
        self.StartOrStopTimer.hide()
        self.ui.resize(self.ui.width() // 2, self.ui.height() // 2)

        # 获取屏幕的分辨率
        screen_geometry = QApplication.desktop().screenGeometry()
        # 计算窗口的新位置，右上角的坐标
        new_x = screen_geometry.width() - self.ui.width()
        new_y = 0
        # 将窗口移动到新位置
        self.ui.move(new_x, new_y)
        self.startAnimation(self.screen_width - 10, self.ui.frameGeometry().topLeft().y(), 'hide', 'right',showtimes=1000)
        self.hidden=True

    def eventFilter(self, obj, event):
        if obj == self.ui and event.type() == QEvent.MouseMove:
            self.mouseMoveEvent(event)
            return True
        elif obj == self.ui and event.type() == QEvent.MouseButtonPress:
            self.mousePressEvent(event)
            return True
        elif obj == self.ui and event.type() == QEvent.MouseButtonRelease:
            self.mouseReleaseEvent(event)
            return True

        elif obj==self.ui and event.type() == QEvent.Enter:
            self.enterEvent(event)
            return True
        elif obj==self.ui and event.type() == QEvent.Leave:
            self.leaveEvent(event)
            return True
        return super().eventFilter(obj, event)

    def enterEvent(self, event):
        self.hide_or_show('show', event)

    def leaveEvent(self, event):
        self.hide_or_show('hide', event)

    def hide_or_show(self, mode, event):
        # 获取窗口左上角x,y
        pos = self.ui.frameGeometry().topLeft()
        if mode == 'show' and self.hidden:
            # 窗口左上角x + 窗口宽度 大于屏幕宽度，从右侧滑出
            if pos.x() + self.ui.width() >= self.screen_width:
                # 需要留10在里边，否则边界跳动
                self.startAnimation(self.screen_width - self.ui.width(), pos.y())
                event.accept()
                self.hidden = False
            # 窗口左上角x 小于0, 从左侧滑出
            elif pos.x() <= 0:
                self.startAnimation(0, pos.y())
                event.accept()
                self.hidden = False
            # 窗口左上角y 小于0, 从上方滑出
            elif pos.y() <= 0:
                self.startAnimation(pos.x(), 0)
                event.accept()
                self.hidden = False
        elif mode == 'hide' and (not self.hidden):
            if pos.x() + self.ui.width() >= self.screen_width:
                # 留10在外面
                self.startAnimation(self.screen_width - 10, pos.y(), mode, 'right')
                event.accept()
                self.hidden = True
            elif pos.x() <= 0:
                # 留10在外面
                self.startAnimation(10 - self.ui.width(), pos.y(), mode, 'left')
                event.accept()
                self.hidden = True
            elif pos.y() <= 0:
                # 留10在外面
                self.startAnimation(pos.x(), 10 - self.ui.height(), mode, 'up')
                event.accept()
                self.hidden = True

    def startAnimation(self, x, y, mode='show', direction=None,showtimes=200):
        animation = QPropertyAnimation(self.ui, b"geometry", self.ui)
        # 滑出动画时长
        animation.setDuration(showtimes)
        # 隐藏时，只留10在外边，防止跨屏
        # QRect限制其大小，防止跨屏
        num = QApplication.desktop().screenCount()
        if mode == 'hide':
            if direction == 'right':
                animation.setEndValue(QRect(x, y, 10, self.ui.height()))
            elif direction == 'left':
                # 多屏时采用不同的隐藏方法，防止跨屏
                if num < 2:
                    animation.setEndValue(QRect(x, y, self.ui.width(), self.ui.height()))
                else:
                    animation.setEndValue(QRect(0, y, 10, self.ui.height()))
            else:
                if num < 2:
                    animation.setEndValue(QRect(x, y, self.ui.width(), self.ui.height()))
                else:
                    animation.setEndValue(QRect(x, 0, self.ui.width(), 10))
        else:
            animation.setEndValue(QRect(x, y, self.ui.width(), self.ui.height()))
        animation.start()



    def mouseMoveEvent(self, e: QMouseEvent):
        if self.ui._tracking:
            if self.ui._resizing:
                delta = e.pos() - self.ui._startPos
                self.ui.resize(self.ui.width() + delta.x(), self.ui.height() + delta.y())
                self.ui._startPos = e.pos()
            else:
                self.ui._endPos = e.pos() - self.ui._startPos
                self.ui.move(self.ui.pos() + self.ui._endPos)

    def mousePressEvent(self, e: QMouseEvent):
        if e.button() == Qt.LeftButton:
            self.ui._startPos = e.pos()
            if e.x() >= self.ui.width() - 10 or e.y() >= self.ui.height() - 10:
                self.ui._resizing = True
                self.ui.setCursor(QCursor(Qt.SizeFDiagCursor))
            else:
                self.ui._resizing = False
                self.ui.setCursor(QCursor(Qt.ClosedHandCursor))
            self.ui._tracking = True

    def mouseReleaseEvent(self, e: QMouseEvent):
        if e.button() == Qt.LeftButton:
            self.ui._tracking = False
            self.ui._resizing = False
            self.ui._startPos = None
            self.ui.setCursor(QCursor(Qt.ArrowCursor))

    def InitPushButton(self):
        self.StartOrStopTimer=self.ui.findChild(QPushButton,'StartOrStopTimer')
        self.toggle_state = True
        self.TimerReady=False
        # print(self.StartOrStopTimer)

        self.AddTimes=self.ui.findChild(QPushButton,'AddTimes')

        self.StartOrStopTimer.clicked.connect(self.toggle_button_click)
        self.AddTimes.clicked.connect(self.AddTimesOne)

    def AddTimesOne(self):
        self.currentSeconds += 60
        print('当前剩余时间：',self.currentSeconds)
        if self.total_seconds==0:
            self.total_seconds=self.currentSeconds
        self.lcdShowDisplay(self.currentSeconds)

    def updateDisplay(self):
        self.lcdShowDisplay(self.total_seconds)

    def UpdataShowData(self):
        self.TextEditShowData(self.ShowData)

    def TextEditShowData(self,ShowData):
        self.ShowImfornation.setPlainText(ShowData)

    def lcdShowDisplay(self, total_seconds):
        # 计算时、分和秒
        hours = total_seconds // 3600
        total_seconds %= 3600
        minutes = total_seconds // 60
        seconds = total_seconds % 60

        # 格式化并显示在lcdNumber中
        timeShow = f'{hours:02d}:{minutes:02d}:{seconds:02d}'
        self.lcdNumber.display(timeShow)

        # 修改 TimerWork 方法

    def toggle_button_click(self):
        # print('sdasdsa')
        if  self.TimerReady:
            if self.toggle_state:
                self.TimerStop()
                self.toggle_state=False
            else:
                self.TimerWork()
                self.toggle_state=True
        else:
            # print('sdasdaccccc')
            self.TimerWork_ready()
            self.TimerReady=True

    def TimerWork_ready(self):
        # 创建一个 QTimer 对象
        self.timer = QTimer(self)
        # self.currentSeconds = self.total_seconds
        self.timer.timeout.connect(self.updateTimer)
        # print('54545')
        self.TimerWork()
    def TimerWork(self):
        if  not self.timer.isActive():
            print('startTimer')
            self.timer.start(1000)

    def TimerStop(self):
        if self.timer.isActive():
            print('stopTimer')
            self.timer.stop()

    def updateTimer(self):
        if self.currentSeconds > 0:
            self.currentSeconds -= 1
            if self.dataNoneFlag:
                self.CheckTime(self.currentSeconds)
            self.lcdShowDisplay(self.currentSeconds)
        else:
            self.TimerStop()

    def CheckTime(self,currentSeconds):
        # print('Checking')
        while self.total_seconds-currentSeconds==self.timeList[0][1]:
            print('Handler')
            self.EventHandlers(self.timeList[0])
            print('backMainThread')
            if self.timeList:
                self.timeList.popleft()

    def EventHandlers(self,eventName):
        print('EventHandlers')
        # 创建EventSignalEmitter的实例，它用于发射信号
        event_signal_emitter = EventSignalEmitter()
        # 连接信号和槽，将showSignal连接到TimerWindowShow的ResetWindow方法
        event_signal_emitter.showSignal.connect(self.ResetWindow)
        # print('startNewThreadOver')
        event_thread = EventHandlerThread(eventName=eventName,ReminMissonData=self.ReminMissonData, event_listener=event_signal_emitter)
        event_thread.setDaemon(True)  # 设置为守护线程
        event_thread.start()

    def ResetWindow(self):
        print('重新设置悬浮部件的位置')
        # 获取屏幕中心坐标
        # 保存原始窗口位置
        self.original_geometry = self.ui.geometry()
        print(self.original_geometry)

        self.ui.animation = QPropertyAnimation(self.ui, b'geometry')
        self.ui.animation.setDuration(1000)  # 设置动画持续时间
        self.ui.animation.setEasingCurve(QEasingCurve.OutElastic)  # 设置缓动曲线

        screen_geometry = QApplication.desktop().availableGeometry()
        center_x = (screen_geometry.width() - self.ui.width()) // 2
        center_y = (screen_geometry.height() - self.ui.height()) // 2
        center_geometry = QRect(center_x, center_y, self.ui.width(), self.ui.height())
        # 设置动画的开始和结束位置
        self.ui.animation.setStartValue( self.original_geometry)
        self.ui.animation.setEndValue(center_geometry)
        # 开始动画
        self.ui.animation.start()
        # 连接动画完成信号到恢复窗口的槽函数
        self.ui.animation.finished.connect(self.wait_before_restore)

    def wait_before_restore(self):
        print('等待3秒后执行恢复动画')
        # 创建一个定时器，等待一定时间后执行恢复窗口动画
        self.timer0 = QTimer(self)
        self.timer0.timeout.connect(self.restore_window)
        self.timer0.start(5000)  # 在这里，等待3秒（3000毫秒）然后执行恢复动画

    def restore_window(self):
        print('准备恢复')
        # 创建一个新的动画对象来执行恢复动画
        self.ui.restore_animation = QPropertyAnimation(self.ui, b'geometry')
        self.ui.restore_animation.setDuration(1000)  # 设置动画持续时间
        self.ui.restore_animation.setEasingCurve(QEasingCurve.OutElastic)  # 设置缓动曲线
        # 设置动画的开始和结束位置
        print(self.ui.geometry())
        self.ui.restore_animation.setStartValue(self.ui.geometry())
        print(self.original_geometry)
        self.ui.restore_animation.setEndValue(self.original_geometry)  # 假设有一个original_geometry属性
        # 开始恢复动画
        print('restore')
        self.ui.restore_animation.start()
        # 连接动画完成信号到清理定时器的槽函数
        self.ui.restore_animation.finished.connect(self.cleanup_timer)

    def cleanup_timer(self):
        print('清理定时器')
        # 停止定时器
        self.timer0.stop()
        # 清理定时器对象
        self.timer0.deleteLater()

    def getTimeList(self,data):
        original_list=list(data.keys())
        # 使用列表推导式将元组内容转换为整数
        result_list = [(int(x), int(y)) for x, y in original_list]
        # 对元组列表按照第一个元素进行倒序排序
        sorted_list = sorted(result_list, key=lambda x: x[0])
        self.timeList=deque(sorted_list)
        self.timeList.append(('End','End'))
        print(self.timeList)
        # self.timeList.sort(reverse=True)

    def getdatalistsHand(self,data):
            print('getdatalistsHand',data)
            self.ReminMissonData={}
            for i in data:
                if i[-1]!=self.TheTimerId:
                    continue
                self.ReminMissonData[(i[0],i[-3])]=i
                # print(self.ReminMissonData)
            print('ReData', self.ReminMissonData)
            self.getTimeList(self.ReminMissonData)

    def showContextMenu(self, pos):
        contextMenu = QMenu(self)

        # personalize_action = QAction('个性化设置', self)
        # personalize_action.triggered.connect(self.personalize)
        personalize_action_menu = QMenu('个性化设置',self)
        contextMenu.addMenu(personalize_action_menu)

        # 创建二级菜单
        font_menu = QMenu("字体样式", self)
        color_menu = QMenu("字体颜色", self)

        font_action = QAction('字体样式', self)
        font_action.triggered.connect(self.fontSetWindow)
        color_action = QAction('字体颜色', self)
        color_action.triggered.connect(self.colorSetWindow)

        personalize_action_menu.addAction(font_action)
        personalize_action_menu.addAction(color_action)


        close_action = QAction('关闭窗口', self)
        close_action.triggered.connect(self.ui.close)

        restart_action = QAction('重新启动', self)
        restart_action.triggered.connect(self.restart)

        contextMenu.addAction(personalize_action_menu.menuAction())
        contextMenu.addAction(close_action)
        contextMenu.addAction(restart_action)

        # 将二级菜单选项添加到二级菜单
        font_menu.addAction(font_action)
        color_menu.addAction(color_action)

        contextMenu.exec_(self.ui.mapToGlobal(pos))

    def fontSetWindow(self):
        font, ok = QFontDialog.getFont(self)
        if ok:
            # 用户选择了字体，将其应用于需要更改字体的部分控件
            self.ShowImfornation.setFont(font)
            # self.setFont(font)

    def colorSetWindow(self):
        color = QColorDialog.getColor()
        if color.isValid():
            # 用户选择了颜色，将其应用于需要更改颜色的控件
            self.ShowImfornation.setStyleSheet(f"color: {color.name()}")
            # self.lcdNumber.setStyleSheet(f"color: {color.name()}")

    def restart(self):
        print('restart')
        print('执行重新启动操作')



class EventSignalEmitter(QObject):
    showSignal = pyqtSignal()

class EventHandlerThread(threading.Thread):
    def __init__(self, eventName,ReminMissonData,event_listener=None):
        super().__init__()
        # print('tttttt')
        self.eventName = tuple(map(str, eventName))
        self.ReminMissonData=ReminMissonData
        self.event_listener = event_listener

    def run(self):
        # 在这里执行事件处理的具体逻辑
        data=self.ReminMissonData[self.eventName][-2]
        if os.path.isfile(data):
            # 初始化pygame
            pygame.init()
            # 指定要播放的音频文件路径
            audio_file_path = data  # 替换为您的音频文件路径
            # 初始化音频模块
            pygame.mixer.init()
            # 加载音频文件
            pygame.mixer.music.load(audio_file_path)
            # 播放音频文件（-1表示循环播放，如果需要播放一次，可以设置为0）
            pygame.mixer.music.play(-1)
            # 等待音频播放完成（如果不加这行，程序会立即退出）
            while pygame.mixer.music.get_busy():
                pygame.time.Clock().tick(10)
            # 停止pygame
            pygame.mixer.quit()
            pygame.quit()
            print(f"This is a file path: {data}")
        else:
            print(f"This is a non-file string: {data}")
            if data[:3]=='播报:':
                # 初始化
                engine = pyttsx3.init()
                # 将要播报的文本
                text = data[3:]
                # 设置语速
                engine.setProperty('rate', 150)  # 可以调整语速, 通常默认为 200
                # 设置音量
                engine.setProperty('volume', 0.9)  # 可以调整音量, 范围在 0 到 1 之间
                # 播报文本
                engine.say(text)
                # 等待语音播报完成
                engine.runAndWait()
                print('这是一个语音播报内容：',data[3:])

            elif data=='悬浮窗弹出':
                self.event_listener.showSignal.emit()
                print('这是一个悬浮窗弹出事件',data)









